package common;

import java.awt.Color;
import java.io.File;

import javax.naming.directory.InvalidAttributesException;



public class Level {

	private LevelData levelData;
	private int levelNr;

	public static final int LEVELAMOUNT = 3;
	
	public Level( File levelFile){
		if( levelFile != null){
			try{
				levelData = getLevelDataFromFile( levelFile);
			}catch( Exception e){
				e.printStackTrace();
			}
		}else{
			try{
				levelData = getTestLevelData( 0);
			}catch( Exception e2){
				e2.printStackTrace();
			}
		}
	}

	public Level( int testLevelNr){
		try{
			levelData = getTestLevelData( testLevelNr);
		}catch( Exception e2){
			e2.printStackTrace();
		}
	}
	
	
	private LevelData getTestLevelData( int testLevelNr) throws InvalidAttributesException{
		levelNr = testLevelNr;
		String[] fieldRow0 = {
				"_ . . _ _ _ . . | . . . ",
				". | . L _ _ . _ _ . | . ",
				". | . . . . _ _ _ . | _ ",
				". L _ _ . . | . . . L . ",
				". . | . | . | . | | | _ ",
				". _ _ . L _ . _ | | | . ",
				". | . . | . . . _ | _ . ",
				". L | . . | . . | L . | ",
				". _ _ . _ L . . | _ _ | ",
				". | . . . . . . | | . | ",
				"_ | . | . _ _ _ | L . | ",
				". . . | . . . . . . . . "
		};
		String[] fieldRow1 = {
				". _ . _ _ . . _ _ _ . . | . . . ",
				"_ L . . . L | . . | . . | L . | ",
				". . _ L . | . . . L L L . | . | ",
				". L L . _ | . | . _ _ . | L . | ",
				". . . . . . . | . . . . . . . . "
		};
		String[] fieldRow2 = {
				"_ _ _ . . | . . . ",
				"L . L . _ _ . | . ",
				". . . _ L _ . . _ ",
				"_ . . | . . . L . ",
				". | . L . _ | | _ ",
				". . _ . _ | . . . ",
				". L _ . _ . . | . "
		};
		
		String[] fieldRowNoWhiteSpaces;
		switch( testLevelNr){
			case 0: fieldRowNoWhiteSpaces = normalizeLevelArray( fieldRow0); break;
			case 1: fieldRowNoWhiteSpaces = normalizeLevelArray( fieldRow1); break;
			case 2: fieldRowNoWhiteSpaces = normalizeLevelArray( fieldRow2); break;
		default: fieldRowNoWhiteSpaces = normalizeLevelArray( fieldRow0); break;
		}
		int[][] startPosition = {
				{0,0},										//P1
				{0, fieldRowNoWhiteSpaces.length - 1}, 		//P2
				{fieldRowNoWhiteSpaces[0].length() - 1, 0}};//P3
		PlayerColor[] startColor = { PlayerColor.Blue,   //P1
							   		 PlayerColor.Red,	 //P2
							   		 PlayerColor.Green}; //P3
		
		LevelData levelData = new LevelData();
		levelData.fieldRow = fieldRowNoWhiteSpaces;
		levelData.startPosition = startPosition;
		levelData.startColor = startColor;
		levelData.colorChangeOnTick = 30;
		
		if( levelData.isValid()){
			return levelData;
		}else{
			throw new InvalidAttributesException( "Testleveldata is not valid: Players have either the same startposition or the same startcolor.");
		}
	}
	
	private LevelData getLevelDataFromFile( File levelFile) throws InvalidAttributesException{
		LevelData levelData = new LevelData();
		/*
		 * TODO load levelfile
		 */
		if( levelData.isValid()){
			return levelData;
		}else{
			System.out.println( "Warning: LevelFile: " + levelFile.getName() + " is not valid, using TestLevel.");
			return getTestLevelData(0);
		}
	}
	/*
	 * return levelarray without whitespaces
	 */
	private String[] normalizeLevelArray(String[] levelArr) throws InvalidAttributesException{
		String[] retArr = new String[levelArr.length];
		int length = 0;
		for( int i = 0; i < levelArr.length; i++){
			String[] split = levelArr[i].split(" ");
			String noWhiteSpaces = "";
			for( String sp : split){
				if( sp != "")
					noWhiteSpaces += sp;
			}
			if( length == 0)
				length = noWhiteSpaces.length();
			else if( length != noWhiteSpaces.length()){
				throw new InvalidAttributesException( "Not all rows have the same length!");
			}
			retArr[i] = noWhiteSpaces;
		}
		return retArr;
	}
	
	public int getRowAmount(){
		return levelData.fieldRow.length;
	}
	public int getColumnAmount(){
		return levelData.fieldRow[0].length();
	}
	public PlayerColor getStartColor( int player){
		return levelData.startColor[ player];
	}
	public int[] getStartPosition( int player){
		return levelData.startPosition[player];
	}
	public int getColorChangeOnTick(){
		return levelData.colorChangeOnTick;
	}
	public int getLevelNr() {
		return levelNr;
	}

	public void setLevelNr(int levelNr) {
		this.levelNr = levelNr;
	}
	public String getField( int row, int col){
		Character c = new Character( levelData.fieldRow[row].toCharArray()[col]);
		return c.toString();
	}

	public boolean canMoveTo(int startX, int startY, PlayerDirection direction) {

		switch(direction) {
		case North:
			if( startY == 0) return false;
			if( getField( startY-1, startX).equals( "_") ||
				getField( startY-1, startX).equals( "L"))
				return false;
		break;
		case East:
			if( startX == getColumnAmount()-1) return false;
			if( getField( startY, startX+1).equals( "|") ||
				getField( startY, startX+1).equals( "L"))
				return false;
		break;
		case South:
			if( startY == getRowAmount()-1) return false;
			if( getField( startY, startX).equals( "_") ||
				getField( startY, startX).equals( "L"))
				return false;
		break;
		case West:
			if( startX == 0) return false;
			if( getField( startY, startX).equals( "|") ||
				getField( startY, startX).equals( "L"))
				return false;
		break;
		default: break;
		}
		
		return true;
	}

	private class LevelData {
		private String[] fieldRow;
		private int[][] startPosition;
		private PlayerColor[] startColor;
		private int colorChangeOnTick = 50;
		
		private boolean isValid(){
			//all different startcolors?
			for( int i = 0; i < 3-1; i++){
				for( int j = i+1; j < 3; j++){
					if( this.startColor[i] == this.startColor[j]){
						return false;
					}
				}
			}
			//all different startpositions?
			for( int i = 0; i < 3-1; i++){
				for( int j = i+1; j < 3; j++){
					if( this.startPosition[i][0] == this.startPosition[j][0] &&
						this.startPosition[i][1] == this.startPosition[j][1]){
						return false;
					}
				}
			}
			return true;
		}
	}
}
